// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

#![allow(dead_code)]
#![allow(unused_imports)]

use crate::gen::Schema::*;
use flatbuffers::EndianScalar;
use std::{cmp::Ordering, mem};
// automatically generated by the FlatBuffers compiler, do not modify

// struct Block, aligned to 8
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq)]
pub struct Block(pub [u8; 24]);
impl Default for Block {
    fn default() -> Self {
        Self([0; 24])
    }
}
impl core::fmt::Debug for Block {
    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
        f.debug_struct("Block")
            .field("offset", &self.offset())
            .field("metaDataLength", &self.metaDataLength())
            .field("bodyLength", &self.bodyLength())
            .finish()
    }
}

impl flatbuffers::SimpleToVerifyInSlice for Block {}
impl<'a> flatbuffers::Follow<'a> for Block {
    type Inner = &'a Block;
    #[inline]
    unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
        <&'a Block>::follow(buf, loc)
    }
}
impl<'a> flatbuffers::Follow<'a> for &'a Block {
    type Inner = &'a Block;
    #[inline]
    unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
        flatbuffers::follow_cast_ref::<Block>(buf, loc)
    }
}
impl<'b> flatbuffers::Push for Block {
    type Output = Block;
    #[inline]
    unsafe fn push(&self, dst: &mut [u8], _written_len: usize) {
        let src = ::core::slice::from_raw_parts(self as *const Block as *const u8, Self::size());
        dst.copy_from_slice(src);
    }
}

impl<'a> flatbuffers::Verifiable for Block {
    #[inline]
    fn run_verifier(
        v: &mut flatbuffers::Verifier,
        pos: usize,
    ) -> Result<(), flatbuffers::InvalidFlatbuffer> {
        use flatbuffers::Verifiable;
        v.in_buffer::<Self>(pos)
    }
}

impl<'a> Block {
    #[allow(clippy::too_many_arguments)]
    pub fn new(offset: i64, metaDataLength: i32, bodyLength: i64) -> Self {
        let mut s = Self([0; 24]);
        s.set_offset(offset);
        s.set_metaDataLength(metaDataLength);
        s.set_bodyLength(bodyLength);
        s
    }

    /// Index to the start of the RecordBlock (note this is past the Message header)
    pub fn offset(&self) -> i64 {
        let mut mem = core::mem::MaybeUninit::<<i64 as EndianScalar>::Scalar>::uninit();
        // Safety:
        // Created from a valid Table for this object
        // Which contains a valid value in this slot
        EndianScalar::from_little_endian(unsafe {
            core::ptr::copy_nonoverlapping(
                self.0[0..].as_ptr(),
                mem.as_mut_ptr() as *mut u8,
                core::mem::size_of::<<i64 as EndianScalar>::Scalar>(),
            );
            mem.assume_init()
        })
    }

    pub fn set_offset(&mut self, x: i64) {
        let x_le = x.to_little_endian();
        // Safety:
        // Created from a valid Table for this object
        // Which contains a valid value in this slot
        unsafe {
            core::ptr::copy_nonoverlapping(
                &x_le as *const _ as *const u8,
                self.0[0..].as_mut_ptr(),
                core::mem::size_of::<<i64 as EndianScalar>::Scalar>(),
            );
        }
    }

    /// Length of the metadata
    pub fn metaDataLength(&self) -> i32 {
        let mut mem = core::mem::MaybeUninit::<<i32 as EndianScalar>::Scalar>::uninit();
        // Safety:
        // Created from a valid Table for this object
        // Which contains a valid value in this slot
        EndianScalar::from_little_endian(unsafe {
            core::ptr::copy_nonoverlapping(
                self.0[8..].as_ptr(),
                mem.as_mut_ptr() as *mut u8,
                core::mem::size_of::<<i32 as EndianScalar>::Scalar>(),
            );
            mem.assume_init()
        })
    }

    pub fn set_metaDataLength(&mut self, x: i32) {
        let x_le = x.to_little_endian();
        // Safety:
        // Created from a valid Table for this object
        // Which contains a valid value in this slot
        unsafe {
            core::ptr::copy_nonoverlapping(
                &x_le as *const _ as *const u8,
                self.0[8..].as_mut_ptr(),
                core::mem::size_of::<<i32 as EndianScalar>::Scalar>(),
            );
        }
    }

    /// Length of the data (this is aligned so there can be a gap between this and
    /// the metadata).
    pub fn bodyLength(&self) -> i64 {
        let mut mem = core::mem::MaybeUninit::<<i64 as EndianScalar>::Scalar>::uninit();
        // Safety:
        // Created from a valid Table for this object
        // Which contains a valid value in this slot
        EndianScalar::from_little_endian(unsafe {
            core::ptr::copy_nonoverlapping(
                self.0[16..].as_ptr(),
                mem.as_mut_ptr() as *mut u8,
                core::mem::size_of::<<i64 as EndianScalar>::Scalar>(),
            );
            mem.assume_init()
        })
    }

    pub fn set_bodyLength(&mut self, x: i64) {
        let x_le = x.to_little_endian();
        // Safety:
        // Created from a valid Table for this object
        // Which contains a valid value in this slot
        unsafe {
            core::ptr::copy_nonoverlapping(
                &x_le as *const _ as *const u8,
                self.0[16..].as_mut_ptr(),
                core::mem::size_of::<<i64 as EndianScalar>::Scalar>(),
            );
        }
    }
}

pub enum FooterOffset {}
#[derive(Copy, Clone, PartialEq)]

/// ----------------------------------------------------------------------
/// Arrow File metadata
///
pub struct Footer<'a> {
    pub _tab: flatbuffers::Table<'a>,
}

impl<'a> flatbuffers::Follow<'a> for Footer<'a> {
    type Inner = Footer<'a>;
    #[inline]
    unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
        Self {
            _tab: flatbuffers::Table::new(buf, loc),
        }
    }
}

impl<'a> Footer<'a> {
    pub const VT_VERSION: flatbuffers::VOffsetT = 4;
    pub const VT_SCHEMA: flatbuffers::VOffsetT = 6;
    pub const VT_DICTIONARIES: flatbuffers::VOffsetT = 8;
    pub const VT_RECORDBATCHES: flatbuffers::VOffsetT = 10;
    pub const VT_CUSTOM_METADATA: flatbuffers::VOffsetT = 12;

    #[inline]
    pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self {
        Footer { _tab: table }
    }
    #[allow(unused_mut)]
    pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr>(
        _fbb: &'mut_bldr mut flatbuffers::FlatBufferBuilder<'bldr>,
        args: &'args FooterArgs<'args>,
    ) -> flatbuffers::WIPOffset<Footer<'bldr>> {
        let mut builder = FooterBuilder::new(_fbb);
        if let Some(x) = args.custom_metadata {
            builder.add_custom_metadata(x);
        }
        if let Some(x) = args.recordBatches {
            builder.add_recordBatches(x);
        }
        if let Some(x) = args.dictionaries {
            builder.add_dictionaries(x);
        }
        if let Some(x) = args.schema {
            builder.add_schema(x);
        }
        builder.add_version(args.version);
        builder.finish()
    }

    #[inline]
    pub fn version(&self) -> MetadataVersion {
        // Safety:
        // Created from valid Table for this object
        // which contains a valid value in this slot
        unsafe {
            self._tab
                .get::<MetadataVersion>(Footer::VT_VERSION, Some(MetadataVersion::V1))
                .unwrap()
        }
    }
    #[inline]
    pub fn schema(&self) -> Option<Schema<'a>> {
        // Safety:
        // Created from valid Table for this object
        // which contains a valid value in this slot
        unsafe {
            self._tab
                .get::<flatbuffers::ForwardsUOffset<Schema>>(Footer::VT_SCHEMA, None)
        }
    }
    #[inline]
    pub fn dictionaries(&self) -> Option<flatbuffers::Vector<'a, Block>> {
        // Safety:
        // Created from valid Table for this object
        // which contains a valid value in this slot
        unsafe {
            self._tab
                .get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'a, Block>>>(
                    Footer::VT_DICTIONARIES,
                    None,
                )
        }
    }
    #[inline]
    pub fn recordBatches(&self) -> Option<flatbuffers::Vector<'a, Block>> {
        // Safety:
        // Created from valid Table for this object
        // which contains a valid value in this slot
        unsafe {
            self._tab
                .get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'a, Block>>>(
                    Footer::VT_RECORDBATCHES,
                    None,
                )
        }
    }
    /// User-defined metadata
    #[inline]
    pub fn custom_metadata(
        &self,
    ) -> Option<flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<KeyValue<'a>>>> {
        // Safety:
        // Created from valid Table for this object
        // which contains a valid value in this slot
        unsafe {
            self._tab.get::<flatbuffers::ForwardsUOffset<
                flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<KeyValue>>,
            >>(Footer::VT_CUSTOM_METADATA, None)
        }
    }
}

impl flatbuffers::Verifiable for Footer<'_> {
    #[inline]
    fn run_verifier(
        v: &mut flatbuffers::Verifier,
        pos: usize,
    ) -> Result<(), flatbuffers::InvalidFlatbuffer> {
        use flatbuffers::Verifiable;
        v.visit_table(pos)?
            .visit_field::<MetadataVersion>("version", Self::VT_VERSION, false)?
            .visit_field::<flatbuffers::ForwardsUOffset<Schema>>("schema", Self::VT_SCHEMA, false)?
            .visit_field::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'_, Block>>>(
                "dictionaries",
                Self::VT_DICTIONARIES,
                false,
            )?
            .visit_field::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'_, Block>>>(
                "recordBatches",
                Self::VT_RECORDBATCHES,
                false,
            )?
            .visit_field::<flatbuffers::ForwardsUOffset<
                flatbuffers::Vector<'_, flatbuffers::ForwardsUOffset<KeyValue>>,
            >>("custom_metadata", Self::VT_CUSTOM_METADATA, false)?
            .finish();
        Ok(())
    }
}
pub struct FooterArgs<'a> {
    pub version: MetadataVersion,
    pub schema: Option<flatbuffers::WIPOffset<Schema<'a>>>,
    pub dictionaries: Option<flatbuffers::WIPOffset<flatbuffers::Vector<'a, Block>>>,
    pub recordBatches: Option<flatbuffers::WIPOffset<flatbuffers::Vector<'a, Block>>>,
    pub custom_metadata: Option<
        flatbuffers::WIPOffset<flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<KeyValue<'a>>>>,
    >,
}
impl<'a> Default for FooterArgs<'a> {
    #[inline]
    fn default() -> Self {
        FooterArgs {
            version: MetadataVersion::V1,
            schema: None,
            dictionaries: None,
            recordBatches: None,
            custom_metadata: None,
        }
    }
}

pub struct FooterBuilder<'a: 'b, 'b> {
    fbb_: &'b mut flatbuffers::FlatBufferBuilder<'a>,
    start_: flatbuffers::WIPOffset<flatbuffers::TableUnfinishedWIPOffset>,
}
impl<'a: 'b, 'b> FooterBuilder<'a, 'b> {
    #[inline]
    pub fn add_version(&mut self, version: MetadataVersion) {
        self.fbb_
            .push_slot::<MetadataVersion>(Footer::VT_VERSION, version, MetadataVersion::V1);
    }
    #[inline]
    pub fn add_schema(&mut self, schema: flatbuffers::WIPOffset<Schema<'b>>) {
        self.fbb_
            .push_slot_always::<flatbuffers::WIPOffset<Schema>>(Footer::VT_SCHEMA, schema);
    }
    #[inline]
    pub fn add_dictionaries(
        &mut self,
        dictionaries: flatbuffers::WIPOffset<flatbuffers::Vector<'b, Block>>,
    ) {
        self.fbb_
            .push_slot_always::<flatbuffers::WIPOffset<_>>(Footer::VT_DICTIONARIES, dictionaries);
    }
    #[inline]
    pub fn add_recordBatches(
        &mut self,
        recordBatches: flatbuffers::WIPOffset<flatbuffers::Vector<'b, Block>>,
    ) {
        self.fbb_
            .push_slot_always::<flatbuffers::WIPOffset<_>>(Footer::VT_RECORDBATCHES, recordBatches);
    }
    #[inline]
    pub fn add_custom_metadata(
        &mut self,
        custom_metadata: flatbuffers::WIPOffset<
            flatbuffers::Vector<'b, flatbuffers::ForwardsUOffset<KeyValue<'b>>>,
        >,
    ) {
        self.fbb_.push_slot_always::<flatbuffers::WIPOffset<_>>(
            Footer::VT_CUSTOM_METADATA,
            custom_metadata,
        );
    }
    #[inline]
    pub fn new(_fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>) -> FooterBuilder<'a, 'b> {
        let start = _fbb.start_table();
        FooterBuilder {
            fbb_: _fbb,
            start_: start,
        }
    }
    #[inline]
    pub fn finish(self) -> flatbuffers::WIPOffset<Footer<'a>> {
        let o = self.fbb_.end_table(self.start_);
        flatbuffers::WIPOffset::new(o.value())
    }
}

impl core::fmt::Debug for Footer<'_> {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        let mut ds = f.debug_struct("Footer");
        ds.field("version", &self.version());
        ds.field("schema", &self.schema());
        ds.field("dictionaries", &self.dictionaries());
        ds.field("recordBatches", &self.recordBatches());
        ds.field("custom_metadata", &self.custom_metadata());
        ds.finish()
    }
}
#[inline]
/// Verifies that a buffer of bytes contains a `Footer`
/// and returns it.
/// Note that verification is still experimental and may not
/// catch every error, or be maximally performant. For the
/// previous, unchecked, behavior use
/// `root_as_footer_unchecked`.
pub fn root_as_footer(buf: &[u8]) -> Result<Footer, flatbuffers::InvalidFlatbuffer> {
    flatbuffers::root::<Footer>(buf)
}
#[inline]
/// Verifies that a buffer of bytes contains a size prefixed
/// `Footer` and returns it.
/// Note that verification is still experimental and may not
/// catch every error, or be maximally performant. For the
/// previous, unchecked, behavior use
/// `size_prefixed_root_as_footer_unchecked`.
pub fn size_prefixed_root_as_footer(buf: &[u8]) -> Result<Footer, flatbuffers::InvalidFlatbuffer> {
    flatbuffers::size_prefixed_root::<Footer>(buf)
}
#[inline]
/// Verifies, with the given options, that a buffer of bytes
/// contains a `Footer` and returns it.
/// Note that verification is still experimental and may not
/// catch every error, or be maximally performant. For the
/// previous, unchecked, behavior use
/// `root_as_footer_unchecked`.
pub fn root_as_footer_with_opts<'b, 'o>(
    opts: &'o flatbuffers::VerifierOptions,
    buf: &'b [u8],
) -> Result<Footer<'b>, flatbuffers::InvalidFlatbuffer> {
    flatbuffers::root_with_opts::<Footer<'b>>(opts, buf)
}
#[inline]
/// Verifies, with the given verifier options, that a buffer of
/// bytes contains a size prefixed `Footer` and returns
/// it. Note that verification is still experimental and may not
/// catch every error, or be maximally performant. For the
/// previous, unchecked, behavior use
/// `root_as_footer_unchecked`.
pub fn size_prefixed_root_as_footer_with_opts<'b, 'o>(
    opts: &'o flatbuffers::VerifierOptions,
    buf: &'b [u8],
) -> Result<Footer<'b>, flatbuffers::InvalidFlatbuffer> {
    flatbuffers::size_prefixed_root_with_opts::<Footer<'b>>(opts, buf)
}
#[inline]
/// Assumes, without verification, that a buffer of bytes contains a Footer and returns it.
/// # Safety
/// Callers must trust the given bytes do indeed contain a valid `Footer`.
pub unsafe fn root_as_footer_unchecked(buf: &[u8]) -> Footer {
    flatbuffers::root_unchecked::<Footer>(buf)
}
#[inline]
/// Assumes, without verification, that a buffer of bytes contains a size prefixed Footer and returns it.
/// # Safety
/// Callers must trust the given bytes do indeed contain a valid size prefixed `Footer`.
pub unsafe fn size_prefixed_root_as_footer_unchecked(buf: &[u8]) -> Footer {
    flatbuffers::size_prefixed_root_unchecked::<Footer>(buf)
}
#[inline]
pub fn finish_footer_buffer<'a, 'b>(
    fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>,
    root: flatbuffers::WIPOffset<Footer<'a>>,
) {
    fbb.finish(root, None);
}

#[inline]
pub fn finish_size_prefixed_footer_buffer<'a, 'b>(
    fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>,
    root: flatbuffers::WIPOffset<Footer<'a>>,
) {
    fbb.finish_size_prefixed(root, None);
}
